package com.aws.server;

import java.io.BufferedReader;
import java.io.IOException;
import java.math.BigInteger;
import java.security.SecureRandom;
import java.util.Iterator;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.PreparedQuery;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.Query.FilterPredicate;
import com.google.gson.Gson;

@SuppressWarnings("serial")
public class ServerUsers extends HttpServlet {
	DatastoreService dataStore = DatastoreServiceFactory.getDatastoreService();

	public void doPost(HttpServletRequest req, HttpServletResponse res)
			throws ServletException, IOException {		
		process(req, res);
	}

	public void process(HttpServletRequest req, HttpServletResponse res)
			throws ServletException, IOException {
		String method = req.getMethod();
		String path = req.getPathInfo();

		System.out.println("[" + method + "] : " + req.getRequestURI());
		System.out.println(path);

		if (path != null) {
			String[] pathComponents = path.split("/");
			String resource = pathComponents[1];

			System.out.println(method + "-" + resource);

			if (method.contains("POST") && resource.contains("login")) {
				login(req, res);
			} else if (method.contains("POST") && resource.contains("logout")) {
				logout(req, res);
			}

			System.out.println("Accion sobre el recurso: " + resource);
		} else {
			System.out.println("Accion sobre una lista de recursos");
		}
	}

	@SuppressWarnings("static-access")
	private void login(HttpServletRequest req, HttpServletResponse res)
			throws IOException {
		System.out.println("Logeando");

		// Cogemos el usuario que nos envia el cliente
		User u = extractUser(req);
		String username = u.getUsername();
		String password = u.getPassword();

		// Buscamos si existe dicho usuario
		Query q = new Query("User").setFilter(new FilterPredicate("username",
				Query.FilterOperator.EQUAL, username));
		PreparedQuery pq = dataStore.prepare(q);
		Iterator<Entity> it = pq.asIterator();
		
		if (it.hasNext()) {
			// Existe el usuario
			Entity e = it.next();
			
			if (password.equals((String) e.getProperty("password"))) {
				// Datos correctos del usuario
				
				System.out.println("Datos correctos");
				
				Query q2 = new Query("Token").setFilter(new FilterPredicate("usuario",
						Query.FilterOperator.EQUAL, username));
				PreparedQuery pq2 = dataStore.prepare(q2);
				Iterator<Entity> it2 = pq2.asIterator();
				
				String token = null;
				
				if (it2.hasNext()) {
					// Existe algun token para el usuario
					Entity e2 = it2.next();
					token = (String) e2.getProperty("token");
				} else {
					// No existe ningun token
					SecureRandom srandom = new SecureRandom();
					String rand = new BigInteger(176, srandom).toString(20);
					token = rand;
					
					Entity e2 = new Entity("Token");
					e2.setProperty("usuario", username);
					e2.setProperty("token", token);
					dataStore.put(e2);
				}
				
				String json = "{\"token\":\"" + token + "\"}";
				res.setContentType("application/json");
				res.getWriter().println(json);				
			} else {
				// No coinciden los datos en la BD
				System.out.println("Datos incorrectos");
				res.setStatus(res.SC_BAD_REQUEST);
			}
		} else {
			// No existe el usuario
			res.setStatus(res.SC_BAD_REQUEST);
		}
	}

	private User extractUser(HttpServletRequest req) throws IOException {
		User u = null;

		Gson gson = new Gson();
		StringBuilder sb = new StringBuilder();
		BufferedReader br = req.getReader();

		String jsonString;
		while ((jsonString = br.readLine()) != null) {
			sb.append(jsonString);
		}
		jsonString = sb.toString();

		try {
			System.out.println("String to be parsed: " + jsonString);
			u = gson.fromJson(jsonString, User.class);
			System.out.println("Event parsed");
		} catch (Exception exc) {
			System.out.println("ERROR parsing Event: " + exc.getMessage());
		}

		return u;
	}

	@SuppressWarnings("static-access")
	private void logout(HttpServletRequest req, HttpServletResponse res) throws IOException {
		Gson gson = new Gson();
		StringBuilder sb = new StringBuilder();
		BufferedReader br = req.getReader();

		String jsonString;
		while ((jsonString = br.readLine()) != null) {
			sb.append(jsonString);
		}
		jsonString = sb.toString();

		Token t = null;
		try {
			System.out.println("String to be parsed: " + jsonString);
			t = gson.fromJson(jsonString, Token.class);
			System.out.println("Event parsed");
			
			Query q = new Query("Token").setFilter(new FilterPredicate("token",
					Query.FilterOperator.EQUAL, t.getToken()));
			PreparedQuery pq = dataStore.prepare(q);
			Iterator<Entity> it = pq.asIterator();
			
			Entity e = null;
			
			if (it.hasNext()) {
				e = it.next();
				dataStore.delete(e.getKey());
			} else {
				res.setStatus(res.SC_BAD_REQUEST);
			}
		} catch (Exception exc) {
			System.out.println("ERROR parsing Event: " + exc.getMessage());
		}
	}
}
